package com.yanxu.nio.c3;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @author 折戟沉沙铁未销
 * @version V1.0
 * @date 2024/12/24-2024
 * @Description: 文件拷贝
 */
public class FileCopyImpl {

    //使用原生的io 流，一个字节一个字节的进行文件的拷贝
    static FileCopy noBufferStreamCopy = new FileCopy() {
        @Override
        public void fileCopy(File source, File target) {
            FileInputStream fileInputStream = null;
            FileOutputStream fileOutputStream = null;
            try {
                fileInputStream = new FileInputStream(source);
                fileOutputStream = new FileOutputStream(target);
                int value;
                while ((value = fileInputStream.read()) != -1) {
                    fileOutputStream.write(value);
                    //fileOutputStream.flush();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (fileInputStream != null) {
                    try {
                        fileInputStream.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
                if (fileOutputStream != null) {
                    try {
                        fileOutputStream.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            }


        }
    };


    //使用原生的io 流，但是使用 buffer 缓冲区的形式进行处理
    FileCopy bufferedStreamCopy = new FileCopy() {
        @Override
        public void fileCopy(File source, File target) {
            InputStream inputStream = null;
            OutputStream outputStream = null;
            try {
                inputStream = new BufferedInputStream(new FileInputStream(source));
                outputStream = new BufferedOutputStream(new FileOutputStream(target));
                byte[] byteArray = new byte[1024];

                //read() 方法返回读取到的字节的长度。
                //-1 表示读到文件的末尾位置了
                int value;
                while ((value = inputStream.read(byteArray, 0, byteArray.length)) != -1) {
                    //在进行写出的时候，不能简单的直接 write(byteArray, 0, 1024);
                    //因为 1024 是数组的长度，在后面的读取中，尤其是快要读完的时候，数据量少的时候，可能只有10个字节的数据了，那么在 byteArray 中只有前三个空间是有数据的。
                    outputStream.write(byteArray, 0, value);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
                if (outputStream != null) {
                    try {
                        outputStream.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            }


        }
    };


    //使用 nio 的方式进行数据的读取。使用  byteBuffer 。
    FileCopy nioBufferCopy = new FileCopy() {
        @Override
        public void fileCopy(File source, File target) {
            FileChannel inChannel = null;
            FileChannel outChannel = null;
            try {
                inChannel = new FileInputStream(source).getChannel();
                outChannel = new FileOutputStream(target).getChannel();
                ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

                while (inChannel.read(byteBuffer) != -1) {  //从 inChannel 中读取数据，读取到的数据写入到 byteBuffer
                    byteBuffer.flip(); //翻转，因为 byteBuffer 中已经有数据了，开始进行读取。
                    while (byteBuffer.hasRemaining()) {
                        outChannel.write(byteBuffer);
                    }
                    //byteBuffer.compact();
                    byteBuffer.clear();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (inChannel != null) {
                    try {
                        inChannel.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
                if (outChannel != null) {
                    try {
                        outChannel.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            }

        }
    };


    FileCopy nioTransferCopy = new FileCopy() {
        @Override
        public void fileCopy(File source, File target) {
            FileChannel inChannel = null;
            FileChannel outChannel = null;
            try {
                inChannel = new FileInputStream(source).getChannel();
                outChannel = new FileOutputStream(target).getChannel();

                long size = inChannel.size();
                long transNum = 0;
                while (transNum != size) {
                    transNum += inChannel.transferTo(transNum, size - transNum, outChannel);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (inChannel != null) {
                    try {
                        inChannel.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (outChannel != null) {
                    try {
                        outChannel.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }


        }
    };

    public static void main(String[] args) {
        noBufferStreamCopy.fileCopy(new File("/home/tomcat.zip"),new File("/home/tomcat1111.zip"));
    }
}